groupby isinstance(f, types.MethodType) in py3
in `core.groupby._whitelist_method_generator` (https://github.com/pandas-dev/pandas/blob/master/pandas/core/groupby.py#L2801)

```
    method_wrapper_template = \
        """def %(name)s(%(sig)s) :
    \"""
    %(doc)s
    \"""
    f = %(self)s.__getattr__('%(name)s')
    return f(%(args)s)"""
    property_wrapper_template = \
        """@property
def %(name)s(self) :
    \"""
    %(doc)s
    \"""
    return self.__getattr__('%(name)s')"""
    for name in whitelist:
        # don't override anything that was explicitly defined
        # in the base class
        if hasattr(GroupBy, name):
            continue
        # ugly, but we need the name string itself in the method.
        f = getattr(klass, name)
        doc = f.__doc__
        doc = doc if type(doc) == str else ''
        if isinstance(f, types.MethodType):
            wrapper_template = method_wrapper_template
            decl, args = make_signature(f)
            # pass args by name to f because otherwise
            # GroupBy._make_wrapper won't know whether
            # we passed in an axis parameter.
            args_by_name = ['{0}={0}'.format(arg) for arg in args[1:]]
            params = {'name': name,
                      'doc': doc,
                      'sig': ','.join(decl),
                      'self': args[0],
                      'args': ','.join(args_by_name)}
        else:
            wrapper_template = property_wrapper_template
            params = {'name': name, 'doc': doc}
        yield wrapper_template % params
```

It looks like `isinstance(f, types.MethodType)` is never evaluating True in py3, so these are all coming out as properties.

PY2:
```
In [1]: import pandas as pd
In [2]: gb = pd.Series(range(10)).groupby(lambda x: x % 2)
In [3]: gb.mad
Out[3]: <bound method SeriesGroupBy.mad of <pandas.core.groupby.SeriesGroupBy object at 0x10f394f10>>
In [4]: gb.mad.__doc__
Out[4]: '\n    \n\nReturn the mean absolute deviation of the values for the requested axis\n\nParameters\n----------\naxis : {index (0)}\nskipna : boolean, default True\n    Exclude NA/null values. If an entire row/column is NA, the result\n    will be NA\nlevel : int or level name, default None\n    If the axis is a MultiIndex (hierarchical), count along a\n    particular level, collapsing into a scalar\nnumeric_only : boolean, default None\n    Include only float, int, boolean columns. If None, will attempt to use\n    everything, then use only numeric data. Not implemented for Series.\n\nReturns\n-------\nmad : scalar or Series (if level specified)\n\n    '
```

PY3:
```
In [1]: import pandas as pd
In [2]: gb = pd.Series(range(10)).groupby(lambda x: x % 2)
In [3]: gb.mad
Out[3]: <function pandas.core.groupby._GroupBy._make_wrapper.<locals>.wrapper>
In [4]: gb.mad.__doc__
In [5]:
```

If we change the condition from `isinstance(f, types.MethodType)` to `not isinstance(f, property)`, a `TypeError` is raised (py3 only):

```
  File "[...]/pandas/core/groupby.py", line 2796, in _whitelist_method_generator
    decl, args = make_signature(f)
  File "[...]/pandas/util/_decorators.py", line 245, in make_signature
    defaults = ('',) * n_wo_defaults + spec.defaults
TypeError: can only concatenate tuple (not "list") to tuple
```

#17600 should make this problem irrelevant eventually, but someone might want to look at it more short-term.