CLN: generate groupby method wrapper code
```
$ grep -r "[^_]exec(" pandas
pandas/compat/__init__.py:    exec("""
pandas/core/groupby.py:        exec(_def_str)
pandas/core/groupby.py:        exec(_def_str)
```

The usage in `compat` is for `raise_with_traceback` where the py2 version is a syntax error in py3.  This is pretty straightforward to de-exec by putting the py2-specific code in a module that only gets imported in py2.  

The usage in `core.groupby` is tougher.  The string being exec'ed defines a method in some cases and property in others.  The property version I think I've got a working fix, but the method version has me stumped.

These `_def_str`s are constructed in `core.groupby._whitelist_method_generator`:

```
    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
```
