BUG: df.agg, df.transform and df.apply use different methods when axis=1 than when axis=0
- [x] closes #16679
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry

This is a splitoff from #21123, to only fix #16679. #19629 will be fixed in a separate PR afterwards.

Passing functions to ``df.agg``, ``df.transform`` and ``df.apply`` may use different methods when ``axis=1``, than when,``axis=0``, and give different results when NaNs are supplied.

Explanation
-------------
Passing the functions in ``SelectionMixin._cython_table`` to ``df.agg`` should defer to use the relevant cython functions. This currently works as expected when ``axis=0``, but not when ``axis=1``.

The reason for this difference is that ``df.aggregate`` currently defers to ``df._aggregate`` when ``axis=0``, but defers to ``df.apply``, when ``axis=1``, and these may give different result when passed functions and the series/frame contains Nan values. I've solved this by transposing df in ``DataFrame._aggragate`` when ``axis=1``, and passing the possibly transposed on to the super method.

Also, ``df.apply`` delegates back to ``df.agg``, when given lists or dicts as inputs, but only works when axis=0. This PR fixes this, so axis=1 works the as axis=0.

The tests have been heavily parametrized, helping ensure that various ways to call the methods now give correct results for both axes.

@WillAyd @jreback (reviewers of #21123)