def dapply(self, fn, pairwise=False, symmetric=True, diagonal=False, block=None, **kwargs):
    search_keys = [k for k, v in kwargs.items() if isinstance(v, list) and len(v) > 1]
    functions = util.make_list(fn)
    search = list(product(functions, util.dict_product(kwargs)))
    results = []
    for fn, kw in search:
        if not pairwise:
            r = self.index.to_series().apply(lambda step: fn(step, **kw))
        else:
            r = apply_pairwise(self, fn,
                               symmetric=symmetric, diagonal=diagonal, block=block,
                               **kw)
        name = [] if len(functions) == 1 else [fn.__name__]
        name += util.dict_subset(kw, search_keys).values()
        if isinstance(r, pd.DataFrame):
            columns = pd.MultiIndex.from_tuples(
                    [tuple(name + util.make_list(c)) for c in r.columns])
            r.columns = columns
        else:
            r.name = tuple(name)
        results.append(r)
    if len(results) > 1:
        result = pd.concat(results, axis=1)
        column_names = [] if len(functions) == 1 else [None]
        column_names += search_keys
        column_names += [None]*(len(result.columns.names)-len(column_names))
        result.columns.names = column_names
        return StepFrame(result)
    else:
        result = results[0]
        if isinstance(result, pd.DataFrame):
            return StepFrame(result)
        else:
            result.name = functions[0].__name__
            return StepSeries(result)