Why is the number of frequencies decomposed in scipy.signal.stft() equal to the hop size?
The number of frequencies 'measured' in the Fourier transform of each time frame is exactly equal to the hop size, 


The number of frequencies is not determined by the hop size, it's determined by the FFT size.  If you don't specify the FFT size, it uses nperseg as the FFT size.


  and it's always evenly spaced between 0 Hz 


Yes, FFT is always evenly spaced, and always starts at 0 Hz.  It doesn't implement Zoom FFT (since it's meant primarily for reconstruction with ISTFT, and Zoom FFT would throw away the required information).


  and half the audio sampling frequency.


Yes, your input is real, so the negative frequencies are redundant, so they are not returned.   nperseg is 100, so nfft is 100, so it returns 100//2+1=51 frequencies (including 0 and Nyquist).

If you give it a complex input, then len(f) will equal nperseg because it returns both the positive and negative frequencies.


  What if I want to have a hop size of 706 samples and 149 measured frequencies between 50 kHz and 65 kHz?


It doesn't support Zoom FFT, so, assuming your sample rate is 65*2 = 130 kHz, you'd need to calculate how many samples you want across the entire bandwidth (= 1292?) and enter that as nfft, and specify noverlap = nperseg - hop, and then ignore the frequencies below 50 kHz that are returned.  

Note that specifying nfft > nperseg returns redundant interpolated information that isn't necessary for reconstruction.