Standardize special case in tz_conversion functions
ATM `_tz_convert_dst` handles iteration and masking differently (and more complicated-ly) than other related functions.  AFAICT the reasoning is that this implementation is performant when the passed `vals` have a high proportion of `iNaT`s.

By changing this special case to conform to the standard pattern, we allow other functions to call this without having to do any special casting, generally simplify things, and open the door to de-duplicating these functions (which this PR also starts doing by implementing `_tz_convert`)

- [ ] closes #xxxx
- [ ] tests added / passed
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry
