def limit_tuple_col(df, tuple_col, lower=None, upper=None):
    """This function applies limits (lower bound and upper bound)
    to values (could be any value type for which min and max are defined)
    given in tuples appearing in `tuple_col` column of dataframe `df`.

    Parameters
    ----------
    df: `pd.DataFrame`
        Input DataFrame
    tuple_col: `str`
        The column of interest consisting of tuples
    lower: `int` or `float` or `double` or `str`
        Any type for which order "<" is defined.
        This input has the same type of values in the tuples,
        and denotes the desired lower bound
    upper: `int` or `float` or `double` or `str`
        Any type for which order "<" is defined.
        This input has the same type of values in the tuples,
        and denotes the desired upper bound

    Returns
    -------
    df : `pd.Dataframe`
        Dataframe of same shape as `df` with only values in `tuple_col` altered
        to satisfy the bounds: `lower`, `upper`
    """
    if lower is not None:
        df[tuple_col] = df.apply(
            lambda row: tuple(
                max(e, lower) for e in row[tuple_col]),
            axis=1)

    if upper is not None:
        df[tuple_col] = df.apply(
            lambda row: tuple(
                min(e, upper) for e in row[tuple_col]),
            axis=1)
    return df