Вы также можете сделать это, используя функцию широковещания, как показано ниже. Объяснение в комментарии
df1 = pd.DataFrame([('10003000100', '10003000500', '22-APR-19'), ('10003001100', '10003001300', '25-MAY-19'), ('10005002001', '10005002500', '30-AUG-19')], columns=('FROM_SERIAL', 'TO_SERIAL', 'TRANSACTION_DATE'))
df2 = df = pd.DataFrame([('10003000150', '30-APR-19'), ('10005002300', '01-OCT-19')], columns=('SERIAL_NO', 'ACTIVATION_DATE'))
## 'df1[["FROM_SERIAL"]]'' is a column vector of size m and 'df2["SERIAL_NO"].values' is row
## vector of size n then broad cast will result array of shape m,n which is
## result of comparing each pair of m and n
compare = (df1[["FROM_SERIAL"]].values<df2["SERIAL_NO"].values) & (df1[["TO_SERIAL"]].values>df2["SERIAL_NO"].values)
mask = np.arange(len(df1)*len(df2)).reshape(-1, len(df2))[compare]
pd.concat([df1.iloc[mask//len(df2)].reset_index(drop=True), df2.iloc[mask%len(df2)].reset_index(drop=True)], axis=1, sort=False)