REF: implement groupby.ops.WrappedCythonFunc
I think this is much closer to "the correct" abstraction here (i find the layered abstractions with similar names in core.groupby hard to follow).  Contains \approx 0 groupby logic (takes ngroups as an argument in some methods) and is only about how to wrap/call/unwrap the libgroupby functions.

There are a few more parts of _cython_operation I'd like to move, but I'm holding off on that pending some non-refactor work that touches those pieces.

No specific plans, but I'm hopeful that something like this can be re-used to de-duplicate logic in nanops and maybe algorithms.

This uses classmethods/staticmethods (i like the explicit statelessness) and passes how+kind as arguments, but an alternative would be to instantiate with how+kind passed to `__init__`.

The only potentially-logical change is that when defining `out_dtype`, this returns "float64" instead of "float".  I haven't checked if that makes a difference on 32bit builds, but after weeks of dealing with np.intp much prefer the explicitness.

@jbrockmendel can you hold off a bit with such refactoring changes to groupby/ops.py until https://github.com/pandas-dev/pandas/pull/40672#issuecomment-811906908 is resolved? > can you hold off a bit with such refactoring

Sure.  The two things I have queued up in this area are 1) a refactor aimed specifically at ameliorating the linked concern and 2) a bugfix where we currently cast int64s to float64s in a lossy way.  When I post them ill put them in "draft" mode and cc you on them.