PERF: array_strptime
array_strptime is conceptually similar to array_to_datetime but stores local values instead of UTC values, then we pass the result through a localization pass that goes through object dtype.  The upside of doing it the current way is that array_strptime does not need a fallback path for when mixed tzs/awareness is detected.  The downside is everything else.

This changes array_strptime to store UTC values and follow the same pattern used by array_to_datetime (hopefully we can move toward sharing more code, though some of that will have to wait until deprecations are enforced in 3.0).  It introduces a fallback _array_strptime_object_fallback that mirrors _array_to_datetime_object that we'll be able to get rid of once the mixed-tz deprecation is enforced in 3.0.

```
vals = np.array(["2016-01-01 02:03:04.567"] * 10**4, dtype=object)
vals2 = np.array([pd.Timestamp(x) for x in vals], dtype=object)
vals3 = np.array([x + "-01:00" for x in vals], dtype=object)

fmt = "%Y-%m-%d %H:%M:%S.%f"

%timeit pd.to_datetime(vals, format=fmt, cache=False)
2.39 ms ± 28.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  # <- main
2.11 ms ± 45.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  # <- PR

%timeit pd.to_datetime(vals2, format=fmt, cache=False)
23.9 ms ± 680 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)   # <- main
10.7 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  # <- PR


%timeit pd.to_datetime(vals3, format=fmt+"%z", cache=False)
99.7 ms ± 1.43 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <- main
63.1 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)  # <- PR
```
> but as far as I understand, _array_strptime_object_fallback can be removed in 3.0 anyway, right?

correct.
 Thanks @jbrockmendel 