Follow up
Rex M provided the answer but just wanted to follow up on what I've also found for posterity.
It seems like you can do either:
<ui:Tabs runat="server">
    <ui:Tab TabText="Blah">
     <ui:Node Url="~/Default.aspx" />
     <ui:Node Url="~/More.aspx" />
     <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
    <ui:Tab TabText="Nanner">
     <ui:Node Url="~/Default.aspx" />
     <ui:Node Url="~/More.aspx" />
     <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
    <ui:Tab TabText="High There">
     <ui:Node Url="~/Default.aspx" />
     <ui:Node Url="~/More.aspx" />
     <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
</ui:Tabs>
OR
<ui:Tabs runat="server">
    <TabItems>
     <ui:Tab InnerHeading="Big Huge Heading" TabText="Big">
      <NodeItems>
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
      </NodeItems>
     </ui:Tab>
    </TabItems>
    <TabItems>
     <ui:Tab InnerHeading="Hi ya" TabText="Hi">
      <NodeItems>
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
       <ui:Node Url="~/Default.aspx" />
      </NodeItems>
     </ui:Tab>
    </TabItems>
</ui:Tabs>
Then within code:
namespace Controls
{
    [ToolboxData("<{0}:Tabs runat=server></{0}:Tabs>"), ParseChildren(true, "TabItems")]
    public class Tabs : BaseControl, INamingContainer
    {
     private TabCollection tabItems;
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
     [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
     public TabCollection TabItems
     {
      get
      {
       if (tabItems == null) 
       { 
        tabItems = new TabCollection(); 
       } 
       return tabItems;
      }
     }
     protected override void Render(HtmlTextWriter writer)
     {
      writer.Write("<div id=\"tabs\" class=\"pane\" style=\"display: none\"><ul>");
      int tabNumber = 1;
      foreach (Tab tab in TabItems)
      {
       string li = string.Format("<li id=\"tab_{0}\"><a href=\"#tab{0}\"><span>{1}</span></a></li>", tabNumber, tab.TabText);
       tabNumber++;
       writer.Write(li);
      }
      writer.Write("</ul>");
      tabNumber = 1;
      foreach (Tab tab in TabItems)
      {
       string div = string.Format("<div id=\"tab{0}\" class=\"pane\"><h1>{1}</h1>", tabNumber, tab.InnerHeading);
       tabNumber++;
       writer.Write(div);
       foreach (Node node in tab.NodeItems)
       {
        string a = string.Format("<a href='{0}'>{1}</a>", node.Url, "Text holder");
        writer.Write(a);
       }
       writer.Write("</div>");
      }
      writer.Write("</div>");
     }
    }
    public class TabCollection : List<Tab> { }
    [ParseChildren(true, "NodeItems")]
    public class Tab
    {
     private string tabText = string.Empty;
     private string innerHeading = string.Empty;
     private string showOn = string.Empty;
     public string TabText
     {
      get { return tabText; }
      set { tabText = value; }
     }
     public string InnerHeading
     {
      get { return innerHeading; }
      set { innerHeading = value; }
     }
     public string ShowOn
     {
      get { return showOn; }
      set { showOn = value; }
     }
     private NodeCollection nodeItems;
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
     [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
     public NodeCollection NodeItems
     {
      get
      {
       if (nodeItems == null)
       {
        nodeItems = new NodeCollection();
       }
       return nodeItems;
      }
     }
    }
    public class NodeCollection : List<Node> { }
    public class Node
    {
     private string url = string.Empty;
     public string Url
     {
      get { return url; }
      set { url = value; }
     }
    }
}
This will obviously be changing (mine's going to be reading from the web.sitemap among other changes), but this should get anyone with the same needs well under their way.