scope.$watchGroup + $interpolation speedup

This is my refactoring of @rodyhaddad's PR #6598

I tried several approaches to clean it up and ended up doing a full circle by keeping the $interpolate optimization that Rody did for parsing but then reimplementing the `$watchGroup` logic inside of the function returned by $interpolate. This resulted in almost no breaking change (the only difference is that fn returned by $interpolate now expects a proper Scope instance rather than an object), removal of all hacks and still preserving the performance boost.

There are two minor todos left before this can be merged, but I'm throwing it out here so that others can start reviewing.

Todos left:
- [ ] remove the single expression optimization from watchGroup, we don't need it any more
- [ ] hide the `compute` fn currently exposed as a property of the fn returned by `$interpolate`. this requires changes to 17 tests.