diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py
index dc15642c9216..45b7182af5de 100644
--- a/lib/matplotlib/axes/_base.py
+++ b/lib/matplotlib/axes/_base.py
@@ -3412,10 +3412,15 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs):
         """
         Set the x-tick labels with list of string labels.
 
+        .. warning::
+            This method should only be used after fixing the tick positions
+            using `~.axes.Axes.set_xticks`. Otherwise, the labels may end up
+            in unexpected positions.
+
         Parameters
         ----------
-        labels : List[str]
-            List of string labels.
+        labels : list of str
+            The label texts.
 
         fontdict : dict, optional
             A dictionary controlling the appearance of the ticklabels.
@@ -3426,12 +3431,13 @@ def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs):
                 'verticalalignment': 'baseline',
                 'horizontalalignment': loc}
 
-        minor : bool, optional
+        minor : bool, default: False
             Whether to set the minor ticklabels rather than the major ones.
 
         Returns
         -------
-        A list of `~.text.Text` instances.
+        labels : list of `~.Text`
+            The labels.
 
         Other Parameters
         -----------------
@@ -3792,12 +3798,17 @@ def get_yticklabels(self, minor=False, which=None):
 
     def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs):
         """
-        Set the y-tick labels with list of strings labels.
+        Set the y-tick labels with list of string labels.
+
+        .. warning::
+            This method should only be used after fixing the tick positions
+            using `~.axes.Axes.set_yticks`. Otherwise, the labels may end up
+            in unexpected positions.
 
         Parameters
         ----------
-        labels : List[str]
-            list of string labels
+        labels : list of str
+            The label texts.
 
         fontdict : dict, optional
             A dictionary controlling the appearance of the ticklabels.
@@ -3808,12 +3819,13 @@ def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs):
                 'verticalalignment': 'baseline',
                 'horizontalalignment': loc}
 
-        minor : bool, optional
+        minor : bool, default: False
             Whether to set the minor ticklabels rather than the major ones.
 
         Returns
         -------
-        A list of `~.text.Text` instances.
+        labels
+            A list of `~.text.Text` instances.
 
         Other Parameters
         ----------------
diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py
index 2101d802264c..13363f7de362 100644
--- a/lib/matplotlib/axis.py
+++ b/lib/matplotlib/axis.py
@@ -1632,6 +1632,11 @@ def set_major_formatter(self, formatter):
         formatter : `~matplotlib.ticker.Formatter`
         """
         cbook._check_isinstance(mticker.Formatter, formatter=formatter)
+        if (isinstance(formatter, mticker.FixedFormatter)
+                and len(formatter.seq) > 0
+                and not isinstance(self.major.locator, mticker.FixedLocator)):
+            cbook._warn_external('FixedFormatter should only be used together '
+                                 'with FixedLocator')
         self.isDefault_majfmt = False
         self.major.formatter = formatter
         formatter.set_axis(self)
@@ -1646,6 +1651,11 @@ def set_minor_formatter(self, formatter):
         formatter : `~matplotlib.ticker.Formatter`
         """
         cbook._check_isinstance(mticker.Formatter, formatter=formatter)
+        if (isinstance(formatter, mticker.FixedFormatter)
+                and len(formatter.seq) > 0
+                and not isinstance(self.minor.locator, mticker.FixedLocator)):
+            cbook._warn_external('FixedFormatter should only be used together '
+                                 'with FixedLocator')
         self.isDefault_minfmt = False
         self.minor.formatter = formatter
         formatter.set_axis(self)
@@ -1697,6 +1707,11 @@ def set_ticklabels(self, ticklabels, *args, minor=False, **kwargs):
         r"""
         Set the text values of the tick labels.
 
+        .. warning::
+            This method should only be used after fixing the tick positions
+            using `.Axis.set_ticks`. Otherwise, the labels may end up in
+            unexpected positions.
+
         Parameters
         ----------
         ticklabels : sequence of str or of `Text`\s
@@ -1718,18 +1733,8 @@ def set_ticklabels(self, ticklabels, *args, minor=False, **kwargs):
                 "3.1", message="Additional positional arguments to "
                 "set_ticklabels are ignored, and deprecated since Matplotlib "
                 "3.1; passing them will raise a TypeError in Matplotlib 3.3.")
-        get_labels = []
-        for t in ticklabels:
-            # try calling get_text() to check whether it is Text object
-            # if it is Text, get label content
-            try:
-                get_labels.append(t.get_text())
-            # otherwise add the label to the list directly
-            except AttributeError:
-                get_labels.append(t)
-        # replace the ticklabels list with the processed one
-        ticklabels = get_labels
-
+        ticklabels = [t.get_text() if hasattr(t, 'get_text') else t
+                      for t in ticklabels]
         if minor:
             self.set_minor_formatter(mticker.FixedFormatter(ticklabels))
             ticks = self.get_minor_ticks()
diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py
index 16f495c04375..377b109f1ec8 100644
--- a/lib/matplotlib/tests/test_axes.py
+++ b/lib/matplotlib/tests/test_axes.py
@@ -5064,11 +5064,15 @@ def test_set_get_ticklabels():
     ax[1].set_title(ha[1])
 
     # set ticklabel to 1 plot in normal way
-    ax[0].set_xticklabels(('a', 'b', 'c', 'd'))
-    ax[0].set_yticklabels(('11', '12', '13', '14'))
+    ax[0].set_xticks(range(10))
+    ax[0].set_yticks(range(10))
+    ax[0].set_xticklabels(['a', 'b', 'c', 'd'])
+    ax[0].set_yticklabels(['11', '12', '13', '14'])
 
     # set ticklabel to the other plot, expect the 2 plots have same label
     # setting pass get_ticklabels return value as ticklabels argument
+    ax[1].set_xticks(ax[0].get_xticks())
+    ax[1].set_yticks(ax[0].get_yticks())
     ax[1].set_xticklabels(ax[0].get_xticklabels())
     ax[1].set_yticklabels(ax[0].get_yticklabels())
 
diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py
index 52befc23f14a..665a23bc2a6e 100644
--- a/lib/matplotlib/tests/test_figure.py
+++ b/lib/matplotlib/tests/test_figure.py
@@ -1,6 +1,7 @@
 from datetime import datetime
 from pathlib import Path
 import platform
+import warnings
 
 from matplotlib import rcParams
 from matplotlib.testing.decorators import image_comparison, check_figures_equal
@@ -317,7 +318,11 @@ def test_autofmt_xdate(which):
     ax.xaxis_date()
 
     ax.xaxis.set_minor_locator(AutoMinorLocator(2))
-    ax.xaxis.set_minor_formatter(FixedFormatter(minors))
+    with warnings.catch_warnings():
+        warnings.filterwarnings(
+            'ignore',
+            'FixedFormatter should only be used together with FixedLocator')
+        ax.xaxis.set_minor_formatter(FixedFormatter(minors))
 
     fig.autofmt_xdate(0.2, angle, 'right', which)
 
diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py
index 5551542a2cb4..f50305301ab8 100644
--- a/lib/matplotlib/ticker.py
+++ b/lib/matplotlib/ticker.py
@@ -345,6 +345,11 @@ def __call__(self, x, pos=None):
 class FixedFormatter(Formatter):
     """
     Return fixed strings for tick labels based only on position, not value.
+
+    .. note::
+        `.FixedFormatter` should only be used together with `.FixedLocator`.
+        Otherwise, the labels may end up in unexpected positions.
+
     """
     def __init__(self, seq):
         """