I have also racked my head on the difference between these two methods for years.
(1) The MATLAB style pyplot wrapper way, "subplots()" with an "s", seem more convenient for most users in a Jupyter notebook environment. There is less syntax to remember and Jupyter updates current figure each time a cell is run, so there is no confusion about which object is the current axes or current figure.
(2) The Object Oriented Method way, "subplot()" with NO "s", is more formal. It really shines when the code will be used in a scripting environment as part of a wider coding module. Since the code is not run interactively at run-time, the formal definition of current figure and axes objects are important for reducing bugs.
(3) Even in a Jupyter notebook environment, when the figure attributes are complex (for publication quality) or are created using python scripts (such as iterators), then the formalism of the Object Oriented Method helps reduce bugs and makes writing the scripts easier. Also, I have not found a way to create 3D projections (wire frame 3D graph) without using the Object Oriented Method.
subplot3d = plt.subplot(111, projection='3d')
These are the main differences from my use cases.
While learning, Matplotlib documentation recommends picking one method and sticking with it. And in Python explicit is better than implicit, so the OO method is preferred. But I prefer a different recommendation from "Python Tools for Scientist" book. Mainly, it's better to learn both, because we need to read other people's code. So practice using one method for a while, then switch to the other method for the next while.
from: https://github.com/ageron/handson-ml3/blob/main/tools_matplotlib.ipynb
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
figure = plt.figure(1, figsize = (12, 4))
subplot3d = plt.subplot(111, projection='3d')
surface = subplot3d.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap=matplotlib.cm.coolwarm, linewidth=0.1)
plt.show()
