A more generalized solution if you have tuples with different number of elements would be to create a custom function like the following
def create_columns_from_tuple(df, tuple_col):
    
    # get max length of tuples
    max_len = df[tuple_col].apply(lambda x: 0 if x is None else len(x)).max()
    
    # select rows with non-empty tuples
    df_full = df.loc[df[tuple_col].notna()]
    
    # create dataframe with exploded tuples
    df_full_exploded = pd.DataFrame(df_full[tuple_col].tolist(),
                                    index=df_full.index, 
                                    columns=[tuple_col + str(n) for n in range(1, max_len+1)])
    
    # merge the two dataframes by index
    result = df.merge(df_full_exploded, left_index=True, right_index=True, how='left')
    
    return result
In this function you pass your dataframe and the name of the tuple column. The function will automatically create as many columns as the maximum length of your tuples.
create_columns_from_tuple(df, tuple_col='b')
#      a       b   b1   b2
# 0  NaN    None  NaN  NaN
# 1  1.0  (1, 2)  1.0  2.0
# 2  2.0  (3, 4)  3.0  4.0
If you have tuples with different number of elements:
df = pd.DataFrame({'a':[None,1, 2], 'b':[None, (1,2,42), (3,4)]}) 
create_columns_from_tuple(df, tuple_col='b')
#      a           b   b1   b2    b3
# 0  NaN        None  NaN  NaN   NaN
# 1  1.0  (1, 2, 42)  1.0  2.0  42.0
# 2  2.0      (3, 4)  3.0  4.0   NaN