<p dir="auto">At present, the draw order order in 3D plots is determined exclusively by sorting the values returned by calling do_3d_projection() in each collection/patch:<br>
</p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/matplotlib/matplotlib/blob/40583b0722fbc5f01bd9e74be84e29cea30ec3a2/lib/mpl_toolkits/mplot3d/axes3d.py#L294-L307">matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py</a>
    </p>
    <p class="mb-0 color-fg-muted">
        Lines 294 to 307
      in
      <a data-pjax="true" class="commit-tease-sha" href="/matplotlib/matplotlib/commit/40583b0722fbc5f01bd9e74be84e29cea30ec3a2">40583b0</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L294" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="294"></td>
          <td id="LC294" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-c"># Calculate projection of collections and patches and zorder them.</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L295" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="295"></td>
          <td id="LC295" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-c"># Make sure they are drawn above the grids.</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L296" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="296"></td>
          <td id="LC296" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-s1">zorder_offset</span> <span class="pl-c1">=</span> <span class="pl-en">max</span>(<span class="pl-s1">axis</span>.<span class="pl-en">get_zorder</span>() </td>
        </tr>

        <tr class="border-0">
          <td id="L297" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="297"></td>
          <td id="LC297" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">                     <span class="pl-k">for</span> <span class="pl-s1">axis</span> <span class="pl-c1">in</span> <span class="pl-s1">self</span>.<span class="pl-en">_get_axis_list</span>()) <span class="pl-c1">+</span> <span class="pl-c1">1</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L298" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="298"></td>
          <td id="LC298" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-k">for</span> <span class="pl-s1">i</span>, <span class="pl-s1">col</span> <span class="pl-c1">in</span> <span class="pl-en">enumerate</span>( </td>
        </tr>

        <tr class="border-0">
          <td id="L299" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="299"></td>
          <td id="LC299" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-en">sorted</span>(<span class="pl-s1">self</span>.<span class="pl-s1">collections</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L300" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="300"></td>
          <td id="LC300" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">                <span class="pl-s1">key</span><span class="pl-c1">=</span><span class="pl-k">lambda</span> <span class="pl-s1">col</span>: <span class="pl-s1">col</span>.<span class="pl-en">do_3d_projection</span>(<span class="pl-s1">renderer</span>), </td>
        </tr>

        <tr class="border-0">
          <td id="L301" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="301"></td>
          <td id="LC301" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">                <span class="pl-s1">reverse</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)): </td>
        </tr>

        <tr class="border-0">
          <td id="L302" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="302"></td>
          <td id="LC302" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-s1">col</span>.<span class="pl-s1">zorder</span> <span class="pl-c1">=</span> <span class="pl-s1">zorder_offset</span> <span class="pl-c1">+</span> <span class="pl-s1">i</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L303" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="303"></td>
          <td id="LC303" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-k">for</span> <span class="pl-s1">i</span>, <span class="pl-s1">patch</span> <span class="pl-c1">in</span> <span class="pl-en">enumerate</span>( </td>
        </tr>

        <tr class="border-0">
          <td id="L304" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="304"></td>
          <td id="LC304" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-en">sorted</span>(<span class="pl-s1">self</span>.<span class="pl-s1">patches</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L305" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="305"></td>
          <td id="LC305" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">                <span class="pl-s1">key</span><span class="pl-c1">=</span><span class="pl-k">lambda</span> <span class="pl-s1">patch</span>: <span class="pl-s1">patch</span>.<span class="pl-en">do_3d_projection</span>(<span class="pl-s1">renderer</span>), </td>
        </tr>

        <tr class="border-0">
          <td id="L306" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="306"></td>
          <td id="LC306" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">                <span class="pl-s1">reverse</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)): </td>
        </tr>

        <tr class="border-0">
          <td id="L307" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="307"></td>
          <td id="LC307" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-s1">patch</span>.<span class="pl-s1">zorder</span> <span class="pl-c1">=</span> <span class="pl-s1">zorder_offset</span> <span class="pl-c1">+</span> <span class="pl-s1">i</span> </td>
        </tr>
    </tbody></table>
  </div>
</div>
<p></p>
<p dir="auto">However, this sorting is not always ideal and a common issue reported by users. I'd propose adding a "force_zorder" optional parameter to Axes3D (defaulting to False) that would ignore the above calculation and instead use the zorder already stored in each collection/patch, i.e.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if self.force_zorder:
    for col in self.collections:
        col.zorder = zorder_offset + col.zorder
    for patch in self.patches:
        patch.zorder = zorder_offset + patch.zorder
else:
    # current code"><pre class="notranslate"><span class="pl-k">if</span> <span class="pl-s1">self</span>.<span class="pl-s1">force_zorder</span>:
    <span class="pl-k">for</span> <span class="pl-s1">col</span> <span class="pl-c1">in</span> <span class="pl-s1">self</span>.<span class="pl-s1">collections</span>:
        <span class="pl-s1">col</span>.<span class="pl-s1">zorder</span> <span class="pl-c1">=</span> <span class="pl-s1">zorder_offset</span> <span class="pl-c1">+</span> <span class="pl-s1">col</span>.<span class="pl-s1">zorder</span>
    <span class="pl-k">for</span> <span class="pl-s1">patch</span> <span class="pl-c1">in</span> <span class="pl-s1">self</span>.<span class="pl-s1">patches</span>:
        <span class="pl-s1">patch</span>.<span class="pl-s1">zorder</span> <span class="pl-c1">=</span> <span class="pl-s1">zorder_offset</span> <span class="pl-c1">+</span> <span class="pl-s1">patch</span>.<span class="pl-s1">zorder</span>
<span class="pl-k">else</span>:
    <span class="pl-c"># current code</span></pre></div>
<p dir="auto">This keeps existing behavior as default, but allows users to override that behavior. This does allow users to specify duplicate or negative zorders, as they can in 2D plots, but that hasn't generated errors in my testing.</p>
<p dir="auto">However, not being at all familiar with the deeper workings, I'd rather get comments/concerns from the matplotlib maintainers and contributors before setting off to produce a full pull request.</p>
<p dir="auto">Thanks!</p>
<h3 dir="auto">Bug report</h3>
<p dir="auto"><strong>Bug summary</strong></p>
<p dir="auto">ImageGrid seems to be broken on 3.0.0?</p>
<p dir="auto"><strong>Code for reproduction</strong></p>

<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="f = plt.figure()
grid = ImageGrid(f, 111, 
                 nrows_ncols=(2, 2),
                 direction='column',
                 label_mode=&quot;L&quot;,
                 cbar_location=&quot;right&quot;,
                 cbar_mode=&quot;single&quot;,
                 cbar_size=&quot;5%&quot;,
                 cbar_pad=&quot;3%&quot;
                 )
axarr = np.array(grid).reshape(2, 2)
for ax in axarr.flatten():
    m = ax.imshow(np.random.random(15**2).reshape((15, 15))+0.5, 
           norm=LogNorm(vmax=2, vmin=0.5), cmap='coolwarm')
plt.colorbar(m, cax=grid.cbar_axes[0], format=FormatStrFormatter('%.2f'))"><pre class="notranslate"><span class="pl-s1">f</span> <span class="pl-c1">=</span> <span class="pl-s1">plt</span>.<span class="pl-en">figure</span>()
<span class="pl-s1">grid</span> <span class="pl-c1">=</span> <span class="pl-v">ImageGrid</span>(<span class="pl-s1">f</span>, <span class="pl-c1">111</span>, 
                 <span class="pl-s1">nrows_ncols</span><span class="pl-c1">=</span>(<span class="pl-c1">2</span>, <span class="pl-c1">2</span>),
                 <span class="pl-s1">direction</span><span class="pl-c1">=</span><span class="pl-s">'column'</span>,
                 <span class="pl-s1">label_mode</span><span class="pl-c1">=</span><span class="pl-s">"L"</span>,
                 <span class="pl-s1">cbar_location</span><span class="pl-c1">=</span><span class="pl-s">"right"</span>,
                 <span class="pl-s1">cbar_mode</span><span class="pl-c1">=</span><span class="pl-s">"single"</span>,
                 <span class="pl-s1">cbar_size</span><span class="pl-c1">=</span><span class="pl-s">"5%"</span>,
                 <span class="pl-s1">cbar_pad</span><span class="pl-c1">=</span><span class="pl-s">"3%"</span>
                 )
<span class="pl-s1">axarr</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">array</span>(<span class="pl-s1">grid</span>).<span class="pl-en">reshape</span>(<span class="pl-c1">2</span>, <span class="pl-c1">2</span>)
<span class="pl-k">for</span> <span class="pl-s1">ax</span> <span class="pl-c1">in</span> <span class="pl-s1">axarr</span>.<span class="pl-en">flatten</span>():
    <span class="pl-s1">m</span> <span class="pl-c1">=</span> <span class="pl-s1">ax</span>.<span class="pl-en">imshow</span>(<span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">random</span>(<span class="pl-c1">15</span><span class="pl-c1">**</span><span class="pl-c1">2</span>).<span class="pl-en">reshape</span>((<span class="pl-c1">15</span>, <span class="pl-c1">15</span>))<span class="pl-c1">+</span><span class="pl-c1">0.5</span>, 
           <span class="pl-s1">norm</span><span class="pl-c1">=</span><span class="pl-v">LogNorm</span>(<span class="pl-s1">vmax</span><span class="pl-c1">=</span><span class="pl-c1">2</span>, <span class="pl-s1">vmin</span><span class="pl-c1">=</span><span class="pl-c1">0.5</span>), <span class="pl-s1">cmap</span><span class="pl-c1">=</span><span class="pl-s">'coolwarm'</span>)
<span class="pl-s1">plt</span>.<span class="pl-en">colorbar</span>(<span class="pl-s1">m</span>, <span class="pl-s1">cax</span><span class="pl-c1">=</span><span class="pl-s1">grid</span>.<span class="pl-s1">cbar_axes</span>[<span class="pl-c1">0</span>], <span class="pl-s1">format</span><span class="pl-c1">=</span><span class="pl-v">FormatStrFormatter</span>(<span class="pl-s">'%.2f'</span>))</pre></div>
<p dir="auto"><strong>Actual outcome</strong><br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/2895034/46876325-f1cafa00-ce35-11e8-955e-c4ae429dd9c0.png"><img src="https://user-images.githubusercontent.com/2895034/46876325-f1cafa00-ce35-11e8-955e-c4ae429dd9c0.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto"><strong>Expected outcome</strong><br>
From 2.2.2<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/2895034/46876255-c3e5b580-ce35-11e8-837e-5880a42bf4f4.png"><img src="https://user-images.githubusercontent.com/2895034/46876255-c3e5b580-ce35-11e8-837e-5880a42bf4f4.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">Note: if I remove all colorbar-related code, it again looks weird, but in a different way:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="f = plt.figure()
grid = ImageGrid(f, 111,  
                 nrows_ncols=(2, 2),
                 direction='column',
                 label_mode=&quot;L&quot;,
                 )
axarr = np.array(grid).reshape(2, 2)
for ax in axarr.flatten():
    m = ax.imshow(np.random.random(15**2).reshape((15, 15))+0.5, 
           norm=LogNorm(vmax=2, vmin=0.5), cmap='coolwarm')"><pre class="notranslate"><span class="pl-s1">f</span> <span class="pl-c1">=</span> <span class="pl-s1">plt</span>.<span class="pl-en">figure</span>()
<span class="pl-s1">grid</span> <span class="pl-c1">=</span> <span class="pl-v">ImageGrid</span>(<span class="pl-s1">f</span>, <span class="pl-c1">111</span>,  
                 <span class="pl-s1">nrows_ncols</span><span class="pl-c1">=</span>(<span class="pl-c1">2</span>, <span class="pl-c1">2</span>),
                 <span class="pl-s1">direction</span><span class="pl-c1">=</span><span class="pl-s">'column'</span>,
                 <span class="pl-s1">label_mode</span><span class="pl-c1">=</span><span class="pl-s">"L"</span>,
                 )
<span class="pl-s1">axarr</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">array</span>(<span class="pl-s1">grid</span>).<span class="pl-en">reshape</span>(<span class="pl-c1">2</span>, <span class="pl-c1">2</span>)
<span class="pl-k">for</span> <span class="pl-s1">ax</span> <span class="pl-c1">in</span> <span class="pl-s1">axarr</span>.<span class="pl-en">flatten</span>():
    <span class="pl-s1">m</span> <span class="pl-c1">=</span> <span class="pl-s1">ax</span>.<span class="pl-en">imshow</span>(<span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">random</span>(<span class="pl-c1">15</span><span class="pl-c1">**</span><span class="pl-c1">2</span>).<span class="pl-en">reshape</span>((<span class="pl-c1">15</span>, <span class="pl-c1">15</span>))<span class="pl-c1">+</span><span class="pl-c1">0.5</span>, 
           <span class="pl-s1">norm</span><span class="pl-c1">=</span><span class="pl-v">LogNorm</span>(<span class="pl-s1">vmax</span><span class="pl-c1">=</span><span class="pl-c1">2</span>, <span class="pl-s1">vmin</span><span class="pl-c1">=</span><span class="pl-c1">0.5</span>), <span class="pl-s1">cmap</span><span class="pl-c1">=</span><span class="pl-s">'coolwarm'</span>)</pre></div>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/2895034/46876557-89304d00-ce36-11e8-88ab-3f22f63941b6.png"><img src="https://user-images.githubusercontent.com/2895034/46876557-89304d00-ce36-11e8-88ab-3f22f63941b6.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto">Seems like maybe all axes take up the whole figure, and so cover the rest?.. Just a guess.</p>
<p dir="auto"><strong>Matplotlib version</strong></p>

<ul dir="auto">
<li>Operating system: Ubuntu 16.04</li>
<li>Matplotlib version: 3.0.0</li>
<li>Matplotlib backend (<code class="notranslate">print(matplotlib.get_backend())</code>): inline</li>
<li>Python version: 3.5.2</li>
<li>Jupyter version (if applicable): Jupyter Lab 0.33.6</li>
</ul>