CLN/ERR: str.cat internals
This is mainly a clean-up of internal methods for `str.cat` that I didn't want to touch within #20347.

~~As a side benefit of changing the implementation, this also solves #22721. Finally, I've also added a better message for TypeErrors (closes #22722)~~

~~closes #22721~~
~~closes #22722~~
- [x] tests modified / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry

Here's the ASV output (the original implementation of this PR (see first commit) that used more higher-level pandas-functions like `fillna`, `drop_na`, etc. was up to three times slower, so I tweaked it some more, and actually believe that the last solution with `interleave_sep` is the most elegant anyway):
```
       before           after         ratio
     [37455764]       [4d1710f1]
         10.9±1ms         9.11±1ms    ~0.83  strings.Cat.time_cat(0, ',', '-', 0.0)
         9.55±1ms         10.9±0ms    ~1.15  strings.Cat.time_cat(0, ',', '-', 0.001)
         12.5±2ms         14.1±2ms    ~1.12  strings.Cat.time_cat(0, ',', '-', 0.15)
         9.94±1ms       9.23±0.7ms     0.93  strings.Cat.time_cat(0, ',', None, 0.0)
         14.3±2ms         8.68±1ms    ~0.61  strings.Cat.time_cat(0, ',', None, 0.001)
-        13.7±1ms       11.7±0.8ms     0.86  strings.Cat.time_cat(0, ',', None, 0.15)
       9.11±0.7ms         7.81±2ms    ~0.86  strings.Cat.time_cat(0, None, '-', 0.0)
       9.38±0.8ms         10.9±1ms    ~1.17  strings.Cat.time_cat(0, None, '-', 0.001)
         11.4±2ms         10.9±2ms     0.96  strings.Cat.time_cat(0, None, '-', 0.15)
         13.4±2ms       9.38±0.6ms    ~0.70  strings.Cat.time_cat(0, None, None, 0.0)
         9.23±2ms         11.7±1ms    ~1.27  strings.Cat.time_cat(0, None, None, 0.001)
         10.2±2ms         10.9±1ms     1.08  strings.Cat.time_cat(0, None, None, 0.15)
-        70.3±4ms         54.7±4ms     0.78  strings.Cat.time_cat(3, ',', '-', 0.0)
         62.5±4ms        46.9±20ms    ~0.75  strings.Cat.time_cat(3, ',', '-', 0.001)
        93.8±10ms        66.4±10ms    ~0.71  strings.Cat.time_cat(3, ',', '-', 0.15)
         62.5±4ms         62.5±4ms     1.00  strings.Cat.time_cat(3, ',', None, 0.0)
+        46.9±4ms         85.9±4ms     1.83  strings.Cat.time_cat(3, ',', None, 0.001)
         52.1±2ms         50.8±6ms     0.97  strings.Cat.time_cat(3, ',', None, 0.15)
         50.8±8ms         54.7±6ms     1.08  strings.Cat.time_cat(3, None, '-', 0.0)
         54.7±4ms         62.5±4ms    ~1.14  strings.Cat.time_cat(3, None, '-', 0.001)
         62.5±5ms         54.7±3ms    ~0.88  strings.Cat.time_cat(3, None, '-', 0.15)
         46.9±4ms         39.1±0ms    ~0.83  strings.Cat.time_cat(3, None, None, 0.0)
         46.9±8ms         58.6±6ms    ~1.25  strings.Cat.time_cat(3, None, None, 0.001)
         46.9±9ms         54.7±4ms    ~1.17  strings.Cat.time_cat(3, None, None, 0.15)
                                                                  ^  ^     ^     ^
                                                                  |  |     |     |
                                                         other_cols  |   na_rep  |
                                                                     |           |
                                                                    sep        na_frac
```

There's a bunch of noise in there, but by and large, things don't look so bad IMO. Especially, when one excludes the not-so-common worst-case scenario of a very small but non-zero amount of NaNs (`na_frac=0.001`):
```
       before           after         ratio
     [37455764]       [4d1710f1]
         10.9±1ms         9.11±1ms    ~0.83  strings.Cat.time_cat(0, ',', '-', 0.0)
         12.5±2ms         14.1±2ms    ~1.12  strings.Cat.time_cat(0, ',', '-', 0.15)
         9.94±1ms       9.23±0.7ms     0.93  strings.Cat.time_cat(0, ',', None, 0.0)
-        13.7±1ms       11.7±0.8ms     0.86  strings.Cat.time_cat(0, ',', None, 0.15)
       9.11±0.7ms         7.81±2ms    ~0.86  strings.Cat.time_cat(0, None, '-', 0.0)
         11.4±2ms         10.9±2ms     0.96  strings.Cat.time_cat(0, None, '-', 0.15)
         13.4±2ms       9.38±0.6ms    ~0.70  strings.Cat.time_cat(0, None, None, 0.0)
         10.2±2ms         10.9±1ms     1.08  strings.Cat.time_cat(0, None, None, 0.15)
-        70.3±4ms         54.7±4ms     0.78  strings.Cat.time_cat(3, ',', '-', 0.0)
         62.5±4ms        46.9±20ms    ~0.75  strings.Cat.time_cat(3, ',', '-', 0.001)
        93.8±10ms        66.4±10ms    ~0.71  strings.Cat.time_cat(3, ',', '-', 0.15)
         62.5±4ms         62.5±4ms     1.00  strings.Cat.time_cat(3, ',', None, 0.0)
         52.1±2ms         50.8±6ms     0.97  strings.Cat.time_cat(3, ',', None, 0.15)
         50.8±8ms         54.7±6ms     1.08  strings.Cat.time_cat(3, None, '-', 0.0)
         62.5±5ms         54.7±3ms    ~0.88  strings.Cat.time_cat(3, None, '-', 0.15)
         46.9±4ms         39.1±0ms    ~0.83  strings.Cat.time_cat(3, None, None, 0.0)
         46.9±9ms         54.7±4ms    ~1.17  strings.Cat.time_cat(3, None, None, 0.15)
                                                                  ^  ^     ^     ^
                                                                  |  |     |     |
                                                         other_cols  |   na_rep  |
                                                                     |           |
                                                                    sep        na_frac
```