This is achievable with EL 3.0 stream API. My initial attempt was:
<h:panelGroup rendered="#{component.children.stream().filter(c -> c.rendered).count() gt 1}">
    <h:outputText value="title" />
    <h:panelGroup rendered="#{false}">item1</h:panelGroup>
    <h:panelGroup rendered="#{false}">item2</h:panelGroup>
    <h:panelGroup rendered="#{false}">item3</h:panelGroup>
</h:panelGroup>
However, that didn't work quite well. It unexpectedly ran into an infinite loop which ultimately ended with an OutOfMemoryError. It appears that #{component} EL variable still represents the previous component at the moment the rendered attribute is consulted. This is a bit of a chicken-egg issue: the #{component} for current component is only injected if its rendered attribute evaluates true.
Given that, I can see two more options: explicitly find the component by ID as below,
<h:panelGroup id="foo" rendered="#{component.findComponent('foo').children.stream().filter(c -> c.rendered).count() gt 1}">
    <h:outputText value="title" />
    <h:panelGroup rendered="#{false}">item1</h:panelGroup>
    <h:panelGroup rendered="#{false}">item2</h:panelGroup>
    <h:panelGroup rendered="#{false}">item3</h:panelGroup>
</h:panelGroup>
or let it print some CSS class which in turn does a display:none;.
<h:panelGroup styleClass="#{component.children.stream().filter(c -> c.rendered).count() gt 1 ? 'show' : 'hide'}">
    <h:outputText value="title" />
    <h:panelGroup rendered="#{false}">item1</h:panelGroup>
    <h:panelGroup rendered="#{false}">item2</h:panelGroup>
    <h:panelGroup rendered="#{false}">item3</h:panelGroup>
</h:panelGroup>